home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / cmds / kgcore / RCS / kgcore.c,v < prev    next >
Encoding:
Text File  |  1992-07-23  |  18.7 KB  |  748 lines

  1. head     1.2;
  2. branch   ;
  3. access   ;
  4. symbols  ;
  5. locks    jhh:1.2; strict;
  6. comment  @ * @;
  7.  
  8.  
  9. 1.2
  10. date     91.05.23.12.28.05;  author mendel;  state Exp;
  11. branches ;
  12. next     1.1;
  13.  
  14. 1.1
  15. date     89.04.11.09.08.49;  author mendel;  state Exp;
  16. branches ;
  17. next     ;
  18.  
  19.  
  20. desc
  21. @kgcore program. Grap a core image from a Sprite kernel that is useable with
  22. the Sprite kgdb debugger.
  23. @
  24.  
  25.  
  26. 1.2
  27. log
  28. @Modified to handle the case when kernelDataStart is wrong because the
  29. machine panic'ed when it ran out of memory.
  30. @
  31. text
  32. @/* 
  33.  * kgcore.c --
  34.  *
  35.  *    Program that reads the image of a Sprite kernel from a
  36.  *    Sprite machine using the debugger interface.
  37.  *
  38.  * Copyright 1988 Regents of the University of California
  39.  * Permission to use, copy, modify, and distribute this
  40.  * software and its documentation for any purpose and without
  41.  * fee is hereby granted, provided that the above copyright
  42.  * notice appear in all copies.  The University of California
  43.  * makes no representations about the suitability of this
  44.  * software for any purpose.  It is provided "as is" without
  45.  * express or implied warranty.
  46.  */
  47.  
  48. #ifndef lint
  49. static char rcsid[] = "$Header: /sprite/users/mendel/src/kgcore/RCS/kgcore.c,v 1.1 89/04/11 09:08:49 mendel Exp Locker: mendel $ SPRITE (Berkeley)";
  50. #endif not lint
  51.  
  52. #include <errno.h>
  53. #include <option.h>
  54. #include <stdio.h>
  55. #include <string.h>
  56. #include <sys/file.h>
  57. #include <kernel/dbg.h>
  58. #include <stdlib.h>
  59.  
  60. #include <signal.h>
  61. #include <sys/types.h>
  62. #include <sys/socket.h>
  63. #include <sys/time.h>
  64. #include <netinet/in.h>
  65. #include <netdb.h>
  66. #include <sgtty.h>
  67.  
  68. /*
  69.  * Library imports:
  70.  */
  71.  
  72. extern void panic();
  73. /*
  74.  * Message buffers for handling the Sprite debugger interface. This routines
  75.  * were stolen from the sprite debugger Kgdb and Kdbx. 
  76.  */
  77. static Dbg_Msg    msg;
  78. static int    msgSize;
  79. #define    MAX_TRANSFER_SIZE    1024
  80. #define    REPLY_BUFFER_SIZE    4096
  81. static    char    replyBuffer[REPLY_BUFFER_SIZE];
  82. static    char    requestBuffer[DBG_MAX_REQUEST_SIZE];
  83. static    int    msgNum = 0;
  84.  
  85. static void    RecvReply();
  86.  
  87. static    struct sockaddr_in    remote;
  88. int                kdbxTimeout = 1;
  89. static    int            netSocket;
  90.  
  91. char    *outputFileName = "vmcore";
  92. int    debug = 0;
  93. int    pageSize;
  94. int    dontDumpCode = 0;
  95. int    dumpFileCache = 0;
  96.  
  97. Option optionArray[] = {
  98.     {OPT_STRING, "o", (char *) &outputFileName,
  99.     "Output file for core dump"},
  100.     {OPT_TRUE, "v", (char *) &debug,
  101.     "Print out progress info."},
  102.     {OPT_TRUE, "nt", (char *) &dontDumpCode,
  103.     "Don't include the kernel text segment in dump."},
  104.     {OPT_TRUE, "c", (char *) &dumpFileCache,
  105.     "Include the file system block cache in dump."},
  106. };
  107. #ifndef sprite
  108. extern char *sys_errlist[];
  109. #endif /* sprite */
  110.  
  111. /*
  112.  *----------------------------------------------------------------------
  113.  *
  114.  * CreateSocket --
  115.  *
  116.  *    Creates a UDP socket connected to the Sprite host's kernel 
  117.  *    debugger port.
  118.  *
  119.  * Results:
  120.  *    The stream ID of the socket.
  121.  *
  122.  * Side effects:
  123.  *    None.
  124.  *
  125.  *----------------------------------------------------------------------
  126.  */
  127. int
  128. CreateSocket(spriteHostName)
  129.     char    *spriteHostName;
  130. {
  131.     int            socketID;
  132.     struct hostent     *hostPtr;
  133.  
  134.     hostPtr = gethostbyname(spriteHostName);
  135.     if (hostPtr == (struct hostent *) NULL) {
  136.     (void) fprintf(stderr, "CreateSocket: unknown host \"%s\"\n",
  137.         spriteHostName);
  138.     exit(1);
  139.     }
  140.     if (hostPtr->h_addrtype != AF_INET) {
  141.     (void) fprintf(stderr, "CreateSocket: bad address type for host %s\n", 
  142.         spriteHostName);
  143.     exit(2);
  144.     }
  145.  
  146.     socketID = socket(AF_INET, SOCK_DGRAM, 0);
  147.     if (socketID < 0) {
  148.     perror("CreateSocket: socket");
  149.     exit(3);
  150.     }
  151.  
  152.     bzero((char *) &remote, sizeof(remote));
  153.     bcopy((char *) hostPtr->h_addr, (char *) &remote.sin_addr,
  154.         hostPtr->h_length);
  155.     remote.sin_port = htons(DBG_UDP_PORT);
  156.     remote.sin_family = AF_INET;
  157.  
  158.     if (connect(socketID, (struct sockaddr *) &remote, sizeof(remote)) < 0) {
  159.     perror("CreateSocket: connect");
  160.     exit(4);
  161.     }
  162.  
  163.     return(socketID);
  164. }
  165.  
  166. /*
  167.  * ----------------------------------------------------------------------------
  168.  *
  169.  *  SendRequest --
  170.  *
  171.  *     Send a request message to the kernel.
  172.  *
  173.  * Results:
  174.  *     None.
  175.  *
  176.  * Side effects:
  177.  *     None.
  178.  * ----------------------------------------------------------------------------
  179.  */
  180. static void
  181. SendRequest(numBytes)
  182.     int    numBytes;
  183. {
  184.     Dbg_Opcode    opcode;
  185.  
  186.     msgSize = numBytes;
  187.     msgNum++;
  188.     *(int *)requestBuffer = msgNum;
  189. #ifdef notdef
  190.     bcopy((char *) &msg, requestBuffer + 4, 2);
  191.     bcopy(((char *) &msg)+4, requestBuffer + 6, numBytes-2);
  192. #endif
  193.     bcopy((char *)&msg, requestBuffer + 4, numBytes);
  194.     if (write(netSocket, requestBuffer, numBytes + 4) < numBytes + 4) {
  195.     panic("SendRequest: Couldn't write to the kernel socket\n");
  196.     return;
  197.     }
  198.     opcode = (Dbg_Opcode) msg.opcode;
  199.     if (opcode == DBG_DETACH) {
  200.     int    dummy;
  201.     /*
  202.      * Wait for explicit acknowledgments of these packets.
  203.      */
  204.     RecvReply(opcode, 4, (char *) &dummy, (int *) NULL, 1);
  205.     }
  206. }
  207.  
  208. /*
  209.  * ----------------------------------------------------------------------------
  210.  *
  211.  *  RecvReply --
  212.  *
  213.  *     Receive a reply from the kernel.
  214.  *
  215.  * Results:
  216.  *     None.
  217.  *
  218.  * Side effects:
  219.  *     None.
  220.  * ----------------------------------------------------------------------------
  221.  */
  222.  
  223.     /* ARGSUSED */
  224. static void
  225. RecvReply(opcode, numBytes, destAddr, readStatusPtr, timeout)
  226.     Dbg_Opcode    opcode;
  227.     int        numBytes;
  228.     char    *destAddr;
  229.     int        *readStatusPtr;
  230.     int        timeout;
  231. {
  232.     int        status;
  233.     int        readMask;
  234.     struct    timeval    interval;
  235.     int        bytesRead;
  236.  
  237.  
  238.     if (numBytes + 8 > REPLY_BUFFER_SIZE) {
  239.     panic("numBytes <%d> > REPLY_BUFFER_SIZE <%d>\n",
  240.             numBytes + 8, REPLY_BUFFER_SIZE);
  241.     }
  242.     interval.tv_sec = kdbxTimeout;
  243.     interval.tv_usec = 0;
  244.     do {
  245.     if (timeout) {
  246.         int    numTimeouts;
  247.  
  248.         numTimeouts = 0;
  249.         /*
  250.          * Loop timing out and sending packets until a new packet
  251.          * has arrived.
  252.          */
  253.         do {
  254.         readMask = 1 << netSocket;
  255.         status = select(32, &readMask, (int *) NULL,
  256.             (int *) NULL, &interval);
  257.         if (status == 1) {
  258.             break;
  259.         } else if (status == -1) {
  260.             panic("RecvReply: Couldn't select on socket.\n");
  261.         } else if (status == 0) {
  262.             SendRequest(msgSize);
  263.             numTimeouts++;
  264.             if (numTimeouts % 10 == 0) {
  265.             (void) fprintf(stderr, "Timing out and resending\n");
  266.             (void) fflush(stderr);
  267.             }
  268.         }
  269.         } while (1);
  270.     }
  271.     if (opcode == DBG_DATA_READ || opcode == DBG_INST_READ ||
  272.         opcode == DBG_GET_VERSION_STRING || opcode == DBG_GET_DUMP_BOUNDS) {
  273.         /*
  274.          * Data and instruction reads return variable size packets.
  275.          * The first two ints are message number and status.  If
  276.          * the status is OK then the data follows.
  277.          */
  278.  
  279.         bytesRead = read(netSocket, replyBuffer, numBytes+8);
  280.         if (bytesRead < 0) {
  281.         panic("RecvReply: Error reading socket.");
  282.         }
  283.         /*
  284.          * Check message number before the size because this could
  285.          * be an old packet.
  286.          */
  287.         if (*(int *)replyBuffer != msgNum) {
  288.         printf("RecvReply: Old message number = %d, expecting %d\n",
  289.             *(int *)replyBuffer, msgNum);
  290.         fflush(stdout);
  291.         continue;
  292.         }
  293.         if (bytesRead == 8) {
  294.         /*
  295.          * Only 8 bytes so the read failed and there is no data.
  296.          */
  297.         *readStatusPtr = 0;
  298.         return;
  299.         }
  300.         if (opcode == DBG_GET_VERSION_STRING) {
  301.          strncpy(destAddr, (char *)(replyBuffer + 4),numBytes);
  302.          return;
  303.         }
  304.         if (opcode == DBG_GET_DUMP_BOUNDS) {
  305.          bcopy((char *)(replyBuffer + 4), destAddr, numBytes);
  306.         *readStatusPtr = 1;
  307.          return;
  308.         }
  309.         if (bytesRead != numBytes + 8) {
  310.         printf("RecvReply: Short read (1): op=%d exp=%d read=%d",
  311.             opcode, numBytes + 4, bytesRead);
  312.         fflush(stdout);
  313.         continue;
  314.         }
  315.         *readStatusPtr = 1;
  316.         bcopy(replyBuffer + 8, destAddr, numBytes);
  317.         return;
  318.     } else {
  319.         /*
  320.          * Normal request so just read in the message which includes
  321.          * the message number.
  322.          */
  323.         bytesRead = read(netSocket, replyBuffer, numBytes + 4);
  324.         if (bytesRead < 0) {
  325.         panic("RecvReply: Error reading socket (2).");
  326.         }
  327.         /*
  328.          * Check message number before size because it could be
  329.          * an old packet.
  330.          */
  331.         if (*(int *)replyBuffer != msgNum) {
  332.         printf("RecvReply: Old message number = %d, expecting %d\n",
  333.                 *(int *)replyBuffer, msgNum);
  334.         fflush(stdout);
  335.         continue;
  336.         }
  337.         if (bytesRead != numBytes + 4) {
  338.         (void) printf("RecvReply: Short read (2): op=%d exp=%d read=%d",
  339.             opcode, numBytes + 4, bytesRead);
  340.         }
  341.         if (*(int *)replyBuffer != msgNum) {
  342.         continue;
  343.         }
  344.         bcopy(replyBuffer + 4, destAddr, numBytes);
  345.         return;
  346.     }
  347.     } while (1);
  348. }
  349.  
  350. /*
  351.  * ----------------------------------------------------------------------------
  352.  *
  353.  * SendCommand --
  354.  *
  355.  *     Write the command over to the kernel.  
  356.  *
  357.  * Results:
  358.  *     None.
  359.  *
  360.  * Side effects:
  361.  *     None.
  362.  *
  363.  * ----------------------------------------------------------------------------
  364.  */
  365. int
  366. SendCommand(opcode, srcAddr, destAddr, numBytes)
  367.     Dbg_Opcode    opcode;        /* Which command */
  368.     char    *srcAddr;    /* Where to read data from */
  369.     char    *destAddr;    /* Where to write data to */
  370.     int        numBytes;    /* The number of bytes to read or write */
  371. {
  372.     int    status;
  373.  
  374.     msg.opcode = (short) opcode;
  375.  
  376.    switch (opcode) {
  377.     case DBG_GET_STOP_INFO:
  378.         SendRequest(sizeof(msg.opcode));
  379.         RecvReply(opcode, numBytes, destAddr, &status, 1);
  380.         break;
  381.     case DBG_DETACH:
  382.         msg.data.pc = *(int *) srcAddr;
  383.         SendRequest(sizeof(msg.opcode) + sizeof(msg.data.pc));
  384.         break;
  385.     case DBG_GET_VERSION_STRING:
  386.     case DBG_GET_DUMP_BOUNDS:
  387.         SendRequest(sizeof(msg.opcode));
  388.         RecvReply(opcode, numBytes, destAddr, &status, 1);
  389.         break;
  390.     case DBG_INST_READ:
  391.         msg.data.readMem.address = (int) srcAddr;
  392.         msg.data.readMem.numBytes = numBytes;
  393.         SendRequest(sizeof(msg.opcode) + sizeof(Dbg_ReadMem));
  394.         RecvReply(opcode, numBytes, destAddr, &status, 1);
  395.         break;
  396.     case DBG_REBOOT:
  397.         if (numBytes > 0) {
  398.         (void) strcpy(msg.data.reboot.string, (char *)srcAddr);
  399.         }
  400.         msg.data.reboot.stringLength = numBytes;
  401.         SendRequest(sizeof(msg.opcode) +
  402.             sizeof(msg.data.reboot.stringLength) +
  403.             msg.data.reboot.stringLength);
  404.         break;
  405.     default:
  406.         (void) printf("Unknown opcode %d\n", opcode);
  407.     }
  408.     return status;
  409. }
  410.  
  411. /*
  412.  *----------------------------------------------------------------------
  413.  *
  414.  * SkipGap --
  415.  *
  416.  *    Update the file offset pointer of the output file to skip over
  417.  *    a gap in the virtual memory image of a kernel.
  418.  *
  419.  * Results:
  420.  *    None.
  421.  *
  422.  * Side effects:
  423.  *    File offset pointer updated.
  424.  *
  425.  *----------------------------------------------------------------------
  426.  */
  427. void
  428. SkipGap(start, end,coreFile)
  429.     unsigned int start;    /* Starting address of gap. */
  430.     unsigned int end;    /* Ending address of gap. */
  431.     FILE    *coreFile; /* Corefile desciptor. */
  432. {
  433.      int size = (end - start);
  434.  
  435.      if (size > 0) { 
  436.      if (fseek(coreFile,size,1) < 0) {
  437.          (void) fprintf(stderr,"kgcore: Can't seek output file: %s\n",
  438.             sys_errlist[errno]);
  439.          (void) fclose(coreFile);
  440.          exit(1);
  441.      }
  442.     }
  443. }
  444.  
  445. /*
  446.  *----------------------------------------------------------------------
  447.  *
  448.  * CopyMem --
  449.  *
  450.  *    Copy memory from the remote machine into a file.
  451.  *
  452.  * Results:
  453.  *    Number of bytes copied.
  454.  *
  455.  * Side effects:
  456.  *    File pointer updated.
  457.  *
  458.  *----------------------------------------------------------------------
  459.  */
  460. int
  461. CopyMem(start, size, coreFile)
  462.     unsigned int start;        /* Starting address of copy. */
  463.     unsigned int size;        /* Size of copy. */
  464.     FILE    *coreFile;    /* Output file.. */
  465. {
  466.     unsigned int address, endAddress;
  467.     char buffer[MAX_TRANSFER_SIZE];
  468.     int    good;
  469.     int len;
  470.     int    bytes = 0;
  471.  
  472.     /*
  473.      * If the starting address is not a multiple of the desired transfer size
  474.      * do a small transfer to round it up.  
  475.      */
  476.     if (start & (MAX_TRANSFER_SIZE - 1)) {
  477.     len = MAX_TRANSFER_SIZE - (start & (MAX_TRANSFER_SIZE - 1));
  478.     if (len > size) {
  479.         len = size;
  480.     }
  481.     good = SendCommand(DBG_INST_READ,(char *)start,buffer,len);
  482.     if (good) {
  483.          if (fwrite(buffer,len,1,coreFile) != 1) {
  484.          (void) fprintf(stderr,"kgcore: Can't write file outfile: %s\n"
  485.             ,sys_errlist[errno]);
  486.          (void) fclose(coreFile);
  487.          exit(1);
  488.          }
  489.          bytes += len;
  490.     } else {
  491.          SkipGap(start, start + len,coreFile);
  492.     }
  493.     start += len;
  494.     size -= len;
  495.     }
  496.     /*
  497.      * Now that start is aligned correctly, transfer as many as possible
  498.      * MAX_TRANSFER_SIZE units.
  499.      */
  500.     endAddress = start + size;
  501.     for (address = start; (address + MAX_TRANSFER_SIZE)  < endAddress; ) {
  502.     good = SendCommand(DBG_INST_READ,(char *)address,buffer,
  503.                     MAX_TRANSFER_SIZE);
  504.     if (good) {
  505.          if (fwrite(buffer,MAX_TRANSFER_SIZE,1,coreFile) != 1) {
  506.          (void) fprintf(stderr,"kgcore: Can't write file outfile: %s\n"
  507.             ,sys_errlist[errno]);
  508.          (void) fclose(coreFile);
  509.          exit(1);
  510.          }
  511.          bytes += MAX_TRANSFER_SIZE;
  512.          address += MAX_TRANSFER_SIZE;
  513.     } else {
  514.         /*
  515.          * If a read fails we can skip over the whole page. We must be
  516.          * a little careful because the start address maybe invalid
  517.          * but not on a page boundry.
  518.          */
  519.          len = pageSize - (address & (pageSize - 1));
  520.          SkipGap(address,address + len,coreFile);
  521.          address += len;
  522.     }
  523.     }
  524.     /*
  525.      * Do any partial transfer that maybe left over.
  526.      */
  527.     if (address < endAddress) {
  528.     len = endAddress - address;
  529.     good = SendCommand(DBG_INST_READ,(char *)address,buffer,len);
  530.     if (good) {
  531.          if (fwrite(buffer,len,1,coreFile) != 1) {
  532.          (void) fprintf(stderr,"kgcore: Can't write file outfile: %s\n"
  533.             ,sys_errlist[errno]);
  534.          (void) fclose(coreFile);
  535.          exit(1);
  536.          }
  537.          bytes += len;
  538.     } else {
  539.          SkipGap(address,endAddress,coreFile);
  540.     }
  541.     }
  542.     return bytes;
  543. }
  544.  
  545. /*
  546.  *----------------------------------------------------------------------
  547.  *
  548.  * main --
  549.  *
  550.  *    Main program for "kgcore".
  551.  *
  552.  * Results:
  553.  *    None.
  554.  *
  555.  * Side effects:
  556.  *
  557.  *----------------------------------------------------------------------
  558.  */
  559.  
  560. main(argc, argv)
  561.     int        argc;
  562.     char    **argv;
  563. {
  564.     StopInfo    stopInfo;
  565.     char    versionString[100];
  566.     Dbg_DumpBounds bounds;
  567.     FILE    *coreFile;
  568.     int        good;
  569.     int        bytes;
  570.     int        totalBytes = 0;
  571.  
  572.     pageSize = getpagesize();
  573.  
  574.     argc = Opt_Parse(argc, argv, optionArray, Opt_Number(optionArray), 0);
  575.     if (argc != 2) {
  576.     (void) fprintf(stderr, "Usage:  %s [options] hostname\n", argv[0]);
  577.     exit(1);
  578.     }
  579.     /*
  580.      * Connect to the remote machine, read, and print the version string.
  581.      */
  582.     netSocket = CreateSocket(argv[1]);
  583.     (void) SendCommand(DBG_GET_VERSION_STRING, (char *)0, versionString, 100);
  584.     printf("Dumping machine %s kernel:\n%s\n",argv[1],versionString);
  585.     good = SendCommand(DBG_GET_DUMP_BOUNDS, (char *)0, (char *)&bounds, 
  586.                         sizeof(bounds));
  587.     if (!good) {
  588.     (void) fprintf(stderr,"%s: Can't get dump bounds from %s\n",argv[0],
  589.                 argv[1]);
  590.     exit(1);
  591.     }
  592.     /*
  593.      * Check for and correct if data segment grew into stack segments.
  594.      * This can happen if the system panic`ed because it ran out of
  595.      * memory.
  596.      */
  597.     if (bounds.kernelDataStart + bounds.kernelDataSize > 
  598.         bounds.kernelStacksStart) {
  599.     (void) fprintf(stderr,
  600.         "%s: Warning: Data segment spills into stack segment\n", 
  601.             argv[1]);
  602.     (void) fprintf(stderr, 
  603.         "%s: Data segment truncated to 0x%x from 0x%x\n",
  604.             argv[1], bounds.kernelStacksStart,
  605.             bounds.kernelDataStart + bounds.kernelDataSize);
  606.     bounds.kernelDataSize = bounds.kernelStacksStart - 
  607.                 bounds.kernelDataStart;
  608.     }
  609.  
  610.     pageSize = bounds.pageSize;
  611.     /*
  612.      * Open the core file and write the stopInfo and bounds.
  613.      */
  614.     coreFile = fopen(outputFileName,"w");
  615.     if (coreFile == (FILE *) NULL) {
  616.      (void) fprintf(stderr,
  617.          "%s: Can't open %s: %s\n",argv[0],outputFileName,
  618.         sys_errlist[errno]);
  619.       exit(1);
  620.     }
  621.     (void) SendCommand(DBG_GET_STOP_INFO, (char *)NULL, (char *)&stopInfo,
  622.             sizeof(stopInfo));
  623.     if ((fwrite((char *)&stopInfo,sizeof(stopInfo),1,coreFile) != 1) ||
  624.     (fwrite((char *)&bounds,sizeof(bounds),1,coreFile) != 1)) {
  625.      (void) fprintf(stderr,"%s: Can't write file %s: %s\n",argv[0],
  626.         outputFileName,sys_errlist[errno]);
  627.      (void) fclose(coreFile);
  628.      exit(1);
  629.     }
  630.     totalBytes += sizeof(stopInfo) + sizeof(bounds);
  631.  
  632.     /*
  633.      * Dump the kernel code segument.
  634.      */
  635.     if (!dontDumpCode) {
  636.     if (debug) {
  637.         printf("Dumping kernel code 0x%x - 0x%x (%d bytes)...",
  638.             bounds.kernelCodeStart, 
  639.             bounds.kernelCodeStart + bounds.kernelCodeSize,
  640.             bounds.kernelCodeSize);
  641.         fflush(stdout);
  642.     }
  643.     bytes = CopyMem(bounds.kernelCodeStart, bounds.kernelCodeSize,coreFile);
  644.     if (debug) {
  645.         printf(" done %d bytes\n",bytes);
  646.     }
  647.     totalBytes += bytes;
  648.     SkipGap(bounds.kernelCodeStart + bounds.kernelCodeSize,
  649.          bounds.kernelDataStart, coreFile);
  650.     } else {
  651.     if (debug) {
  652.         printf("Skipping text segment to 0x%x\n",bounds.kernelDataStart);
  653.     }
  654.     SkipGap(bounds.kernelCodeStart, bounds.kernelDataStart, coreFile);
  655.     }
  656.     /*
  657.      * Follow the code by the kernel data segument.
  658.      */
  659.     if (debug) {
  660.     printf("Dumping kernel data 0x%x - 0x%x (%d bytes) ...",
  661.         bounds.kernelDataStart, 
  662.         bounds.kernelDataStart + bounds.kernelDataSize,
  663.         bounds.kernelDataSize);
  664.     fflush(stdout);
  665.     }
  666.     bytes = CopyMem(bounds.kernelDataStart, bounds.kernelDataSize, coreFile);
  667.     totalBytes += bytes;
  668.     if (debug) {
  669.      printf(" done %d bytes\n",bytes);
  670.     }
  671.     SkipGap(bounds.kernelDataStart + bounds.kernelDataSize, 
  672.         bounds.kernelStacksStart, coreFile);
  673.     /*
  674.      * Follow the data by the kernel stacks.
  675.      */
  676.     if (debug) {
  677.     printf("Dumping kernel stacks 0x%x - 0x%x (%d bytes) ...",
  678.         bounds.kernelStacksStart, 
  679.         bounds.kernelStacksStart + bounds.kernelStacksSize,
  680.         bounds.kernelStacksSize);
  681.     fflush(stdout);
  682.     }
  683.     bytes = CopyMem(bounds.kernelStacksStart, bounds.kernelStacksSize,coreFile);
  684.     totalBytes += bytes;
  685.     if (debug) {
  686.      printf(" done %d bytes\n",bytes);
  687.     }
  688.     /*
  689.      * And optionally the file system block cache.
  690.      */
  691.     if (dumpFileCache) {
  692.     SkipGap(bounds.kernelStacksStart + bounds.kernelStacksSize, 
  693.         bounds.fileCacheStart, coreFile);
  694.     if (debug) {
  695.         printf("Dumping file cache 0x%x - 0x%x (%d bytes) ...",
  696.             bounds.fileCacheStart, 
  697.             bounds.fileCacheStart + bounds.fileCacheSize,
  698.             bounds.fileCacheSize);
  699.         fflush(stdout);
  700.     }
  701.     bytes = CopyMem(bounds.fileCacheStart, bounds.fileCacheSize, coreFile);
  702.     totalBytes += bytes;
  703.     if (debug) {
  704.          printf(" done %d bytes\n",bytes);
  705.     }
  706.     }
  707.     if (fclose(coreFile) == EOF) {
  708.      (void) fprintf(stderr,"%s: Error closing file %s: %s\n",argv[0],
  709.         outputFileName,sys_errlist[errno]);
  710.     }
  711.  
  712.     printf("%s: Dumped %d bytes from %s into %s.\n",argv[0], totalBytes,
  713.             argv[1], outputFileName);
  714.     exit(0);
  715. }
  716. @
  717.  
  718.  
  719. 1.1
  720. log
  721. @Initial revision
  722. @
  723. text
  724. @d18 1
  725. a18 1
  726. static char rcsid[] = "$Header: /a/newcmds/kmsg/RCS/kmsg.c,v 1.1 88/10/26 10:28:44 ouster Exp $ SPRITE (Berkeley)";
  727. a21 2
  728. #include <host.h>
  729. #include <net.h>
  730. d69 2
  731. a70 2
  732.     {OPT_TRUE, "d", (char *) &debug,
  733.     "Print out debugging info."},
  734. d72 1
  735. a72 1
  736.     "Do not include the kernel code segment in dump."},
  737. d76 3
  738. d158 1
  739. a158 1
  740. #ifdef sparc
  741. d161 1
  742. a161 1
  743. #else
  744. a162 1
  745. #endif
  746. d561 18
  747. @
  748.